package com.hundsun.cprs.yyt.service.account.service.impl;

import java.util.Date;
import java.util.List;

import com.hundsun.cprs.yyt.service.account.dao.QuoteExchangeDao;
import com.hundsun.cprs.yyt.service.account.domain.QuoteExchange;
import com.hundsun.cprs.yyt.service.account.enums.EnumQuoteExchangeLogStatus;
import com.hundsun.cprs.yyt.service.common.dto.IntegralInfo;
import com.hundsun.cprs.yyt.service.common.service.RemoteShopService;
import com.hundsun.cprs.yyt.service.quota.domain.Quota;
import com.hundsun.cprs.yyt.service.quota.service.QuotaHoldService;
import com.hundsun.cprs.yyt.service.system.enums.EnumBussinessParam;
import com.hundsun.cprs.yyt.service.system.service.BusinessParamHelper;
import com.hundsun.cprs.yyt.service.system.service.BussinessParamService;
import com.hundsun.cprs.yyt.util.DoubleUtil;

import org.apache.http.util.Asserts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hundsun.cprs.yyt.common.base.BaseService;
import com.hundsun.cprs.yyt.common.exception.ServiceException;
import com.hundsun.cprs.yyt.service.account.dao.AccountDao;
import com.hundsun.cprs.yyt.service.account.domain.Account;
import com.hundsun.cprs.yyt.service.account.domain.AccountQuotaLog;
import com.hundsun.cprs.yyt.service.account.domain.query.AccountQuery;
import com.hundsun.cprs.yyt.service.account.enums.EnumQuotaTransType;
import com.hundsun.cprs.yyt.service.account.service.AccountQuotaLogService;
import com.hundsun.cprs.yyt.service.account.service.AccountService;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

@Service
public class AccountServiceImpl extends BaseService implements AccountService {
    
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private AccountQuotaLogService quotaLogSerivce;
    @Autowired
    private BussinessParamService bussinessParamService;
    @Autowired
    private RemoteShopService remoteShopService;
    @Autowired
    private QuoteExchangeDao quoteExchangeDao;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private QuotaHoldService quotaHoldService;

    @Override
    public void selectByPage(AccountQuery query) {
        List<Account>  result = accountDao.selectByQuery(query);
        query.compatible(result);
    }

    @Override
    public List<Account> selectByList(AccountQuery query) {
        query.onlyReturnList();
        return accountDao.selectByQuery(query);
    }

    @Override
    public Account createAccount(Account account) {
        accountDao.insert(account);
        return account;
    }

    @Override
    public Account modifyAccount(Account account) {
        accountDao.updateByPrimaryKey(account);
        return account;
    }

    @Override
    public Account getAccountByUserId(Long userId) {
        return accountDao.selectByUserId(userId);
    }

    @Override
    @Deprecated
    @Transactional(isolation=Isolation.READ_COMMITTED)
    public void deductQuota(Long userId, Long amount,String type,String memo) {
        int result = accountDao.updateQuotaByUserId(userId, amount * -1);
        if (result == 0) {
            throw new ServiceException("配额不足");
        }
        Account account = getAccountByUserId(userId);
        AccountQuotaLog log = new AccountQuotaLog();
        log.setFundAccount(account.getFundAccount());
        log.setUserId(account.getUserId());
        log.setTransAmount(new Long(amount));
        log.setTransType(type);
        log.setPostAmount(account.getCurrentQuota());
        log.setPreAmount(log.getPostAmount() + log.getTransAmount());
        log.setTransDate(new Date());
        log.setMemo(memo);
        quotaLogSerivce.log(log);
    }

    @Override
    @Deprecated
    @Transactional(isolation=Isolation.READ_COMMITTED)
    public void addQuota(Long userId, Long amount,String memo) {
        int result = accountDao.updateQuotaByUserId(userId, amount);
        if (result == 0) {
            throw new ServiceException("配额不足");
        }
        Account account = getAccountByUserId(userId);
        AccountQuotaLog log = new AccountQuotaLog();
        log.setFundAccount(account.getFundAccount());
        log.setUserId(account.getUserId());
        log.setTransAmount(new Long(amount));
        log.setTransType(EnumQuotaTransType.TRANS_0201.getCode());
        log.setPostAmount(account.getCurrentQuota());
        log.setPreAmount(log.getPostAmount() - log.getTransAmount());
        log.setTransDate(new Date());
        log.setMemo(memo);
        quotaLogSerivce.log(log);
    }

    @Override
    @Transactional
    public void exchangePoints(Long userId, Long exchangeAmount,Quota quota) {
    	Asserts.notNull(userId, "");
    	Asserts.notNull(exchangeAmount, "");
    	Asserts.notNull(quota, "");
    	
        String logsStatus = EnumQuoteExchangeLogStatus.SUCCESS.getCode();
        String quoteExchangePointRate = "";
        Long pointAmount = exchangeAmount;
        try{
            //1.减少用户配额
            //this.deductQuota(userId,exchangeAmount,EnumQuotaTransType.TRANS_0103.getCode(),"配额兑换积分");
        	quotaHoldService.deductQuota(userId, quota.getId(), exchangeAmount, EnumQuotaTransType.TRANS_0103.getCode(), "配额兑换积分");
            //2.按比例增加用户的积分
            quoteExchangePointRate = BusinessParamHelper.getStringValue(bussinessParamService,EnumBussinessParam.QUOTE_EXCHANGE_POINT_RATE,"1:1");
            String[] rateArray = quoteExchangePointRate.split(":");
            Double rate1 = Double.parseDouble(rateArray[0]);
            Double rate2 = Double.parseDouble(rateArray[1]);
            Double rate = DoubleUtil.div(rate2,rate1);
            Double pointAmountDaoubleValue = DoubleUtil.mul(rate,exchangeAmount);
            pointAmount = pointAmountDaoubleValue.longValue();
            //3.直接对接商城
            IntegralInfo integralInfo = new IntegralInfo();
            integralInfo.setUserId(userId);
            integralInfo.setAmount(pointAmount);
            integralInfo.setMemo("配额兑换积分");
            remoteShopService.changeIntegral(integralInfo);
        }catch (Exception e){
            logsStatus = EnumQuoteExchangeLogStatus.ERROR.getCode();
            logger.error("配额兑换积分出错：" + e);
            throw e;
        }finally {
            //4.独立事务提交，生成配额兑换积分流水
            createLogs(userId,exchangeAmount,pointAmount,logsStatus,quoteExchangePointRate);
        }
    }

    public void createLogs(Long userId, Long exchangeAmount,Long pointAmount,String status,String quoteExchangePointRate){
        DefaultTransactionDefinition defintion = new DefaultTransactionDefinition();
        defintion.setPropagationBehavior(Propagation.REQUIRES_NEW.value());
        defintion.setIsolationLevel(Isolation.READ_COMMITTED.value());
        TransactionStatus transactionStatus = transactionTemplate.getTransactionManager().getTransaction(defintion);
        try{
            QuoteExchange quoteExchange = new QuoteExchange();
            quoteExchange.setChansTime(new Date());
            quoteExchange.setExchangeQuoteAmount(exchangeAmount);
            quoteExchange.setExchangeIntegralAmount(pointAmount);
            quoteExchange.setExchangeRate(quoteExchangePointRate);
            quoteExchange.setStatus(status);
            quoteExchange.setUserId(userId);
            Account account = this.getAccountByUserId(userId);
            quoteExchange.setFundAccount(account.getFundAccount());
            quoteExchange.setUserName(account.getUserName());
            quoteExchangeDao.insert(quoteExchange);

            transactionTemplate.getTransactionManager().commit(transactionStatus);
        } catch(Exception e) {
            transactionTemplate.getTransactionManager().rollback(transactionStatus);
            throw e;
        }
    }

    @Override
    public Long sumRemainingQuotaByQuery(AccountQuery query) {
        query.onlyReturnList();
        return accountDao.sumRemainingQuotaByQuery(query);
    }

    @Override
    @Cacheable(value="YYT:ACCOUNT:INFO",key="#fundAccount")
    public Account getAccountByFundAccountFromCache(String fundAccount) {
        return accountDao.selectByFundAccount(fundAccount);
    }
}
